﻿using Abp;
using Abp.AspNetCore.SignalR.Hubs;
using Abp.Dependency;
using Abp.RealTime;
using Castle.Core.Logging;
using Microsoft.AspNetCore.SignalR;
using Mt.Site.Core.Authorization.Users;
using System;
using System.Linq;
using System.Threading.Tasks;

namespace Mt.Site.Web.OnlineUser
{
    public class OnlineUserUpdater : IOnlineUserUpdater, ITransientDependency
    {
        private readonly IHubContext<AbpCommonHub> _hubContext;

        private readonly IOnlineClientManager _onlineClientManager;

        public ILogger Logger { get; set; }

        public OnlineUserUpdater(
            IHubContext<AbpCommonHub> hubContext, 
            IOnlineClientManager onlineClientManager)
        {
            _hubContext = hubContext;
            _onlineClientManager = onlineClientManager;

            Logger = NullLogger.Instance;
        }
        public void UpdateOnlineUserCount()
        {
            try
            {
                var allUser = _onlineClientManager.GetAllClients();
                var userCount = allUser.Select(c => c.UserId).Distinct().Count();
                var data = new OnlineUserArg
                {
                    UserCount = userCount
                };
                foreach (var onlineClient in allUser)
                {
                    var signalRClient = _hubContext.Clients.Client(onlineClient.ConnectionId);
                    if (signalRClient == null)
                    {
                        Logger.Debug("Can not get user with connectionId " + onlineClient.ConnectionId + " from SignalR hub!");
                        continue;
                    }

                    Abp.Threading.AsyncHelper.RunSync(() => signalRClient.SendAsync("onlineUserRefresh", data));
                }
            }
            catch (Exception ex)
            {
                Logger.Warn("Could not send notification to user" );
                Logger.Warn(ex.ToString(), ex);
            }
        }

        public Task UpdateOnlineUserCountAsync()
        {
            try
            {
                var allUser = _onlineClientManager.GetAllClients();
                var userCount = allUser.Select(c => c.UserId).Distinct().Count();
                var data = new OnlineUserArg
                {
                    UserCount = userCount
                };
                foreach (var onlineClient in allUser)
                {
                    var signalRClient = _hubContext.Clients.Client(onlineClient.ConnectionId);
                    if (signalRClient == null)
                    {
                        Logger.Debug("Can not get user with connectionId " + onlineClient.ConnectionId + " from SignalR hub!");
                        continue;
                    }

                    signalRClient.SendAsync("onlineUserRefresh", data);
                }
            }
            catch (Exception ex)
            {
                Logger.Warn("Could not send notification to user");
                Logger.Warn(ex.ToString(), ex);
            }

            return Task.FromResult(0);
        }

        public Task ExitOnlineUserAsync(IUserIdentifier user)
        {
            var clients = _onlineClientManager.GetAllByUserId(user);
            foreach (var item in clients)
            {
                var signalRclient = _hubContext.Clients.Client(item.ConnectionId);
                if (signalRclient != null)
                {
                    signalRclient.SendAsync("onlineUserExit");
                }
            }
            return Task.FromResult(0);
        }
    }
}
